#include "serverThread.h"
#include "serverException.h"
#include "baseThread.h"
#include "data.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <pthread.h>
#include "sort.h"
#include "serverThread.h"
using namespace std;

ServerThread::~ServerThread(){
	pthread_exit(NULL);//close
}

ServerThread::ServerThread(int conn_fd):conn_fd(conn_fd){
	
}
struct tm ServerThread::unixTime2Str(int n){    		
	char str[100];
    struct tm *time;
    uint16_t year, yday;
    uint8_t month, day, week, hour, minute, second;
    time_t timestamp = n;  /*北京时间2020-06-24 01:16:51*/
/*
	几个用于测试的时间戳和北京时间对应
	1592932611 = 2020-06-24 01:16:51(北京时间) 
	1593541011 = 2020-07-01 02:16:51
	1593526611 = 2020-06-30 22:16:51
*/    

  
    /* 北京时间补偿 */
    timestamp += 8*60*60;
	/* 调用系统函数 */
    time = localtime(&timestamp);
	
	year = time->tm_year;   /* 自1900年算起 */
    month = time->tm_mon;   /* 从1月算起，范围0-11 */
    week = time->tm_wday;   /* 从周末算起，范围0-6 */
    yday = time->tm_yday;  /* 从1月1日算起，范围0-365 */
    day = time->tm_mday;    /* 日: 1-31 */
    hour = time->tm_hour;   /* 小时:0-23点,UTC+0时间 */
    minute = time->tm_min;  /* 分钟:0-59 */
    second = time->tm_sec;  /* 0-60，偶尔出现的闰秒 */
    strftime(str, 100, "%F %T", time);
    /* 时间校正 */
    time->tm_year += 1900;
    time->tm_mon += 1;
    time->tm_wday += 1;
	time->tm_hour += 7;
    /*
    printf("日期:%d-%d-%d 第%d天 星期%d 时间:%d:%d:%d\r\n",
        year, month, day, yday, week, hour, minute, second);
	*/
	/* 格式化时间字符串 */
      /* 2020-07-01 02:16:51 */
//    strftime(str, 100, "%m-%d %H:%M", time);  /* 06-30 22:16 */
	return *time;
}


void ServerThread::run(){
		MatchedLogRec buf;
		int rlen;//结构体MatchedRecLog的长度，匹配的一条日志记录长度
		int flag;//标记变量
		int rcvNum;//接收成功数量计数器变量
		int error;//接收失败数量计数器变量
		while(1){
			/**
		*recv函数 int recv( SOCKET s,char FAR *buf,int len,int flags);   
		*不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。
		*该函数的第一个参数指定接收端套接字描述符；
		*第二个参数指明一个缓冲区，该缓冲区用来存放recv函数接收到的数据；
		*第三个参数指明buf的长度；
		*第四个参数一般置0。
		*
		*/
			rlen = recv(conn_fd,(MatchedLogRec *)&buf,sizeof(MatchedLogRec),0);
			if(rlen<0){
				printf("read fail\n");		
			}else if(rlen == 0){
				printf("read to the end reciver %d datas,fail %d datas\n\n",rcvNum,error);
				printf("已成功接收的登录日志记录共: %d 条！\n\n",rcvNum);
				printf("DMS服务端已完成数据采集与接收！\n\n");
				flag = 1;
				if(flag == 1){
					for(list<MatchedLogRec>::iterator it = matches.begin();it!=matches.end();++it){
					loginDay.push_back(unixTime2Str(it->login_time));//添加一个 登入时间 元素到list集合
					logoutDay.push_back(unixTime2Str(it->logout_time));//添加一个 登出时间 元素到list集合
					}
					//整合数据 日报表 月报表 年报表
					Sort *sort	= new Sort(matches,loginDay,logoutDay);
					sort->sort_day();
					sort->sort_mon();
					sort->sort_year();
					for(list<struct tm >::iterator it = loginDay.begin();it!=loginDay.end();++it){
						//遍历输出 年-月-日 时 ：分 ：秒
						cout<<it->tm_year<<"-"<<it->tm_mon<<"-"<<it->tm_mday<<"\t" <<it->tm_hour<<":"<<it->tm_min<<":"<<it->tm_sec<<endl;			
					}		
				}
				delete this;	
			}else if(rlen == 80){
				printf("成功接收一条已匹配的日志记录... \n\n");			
				rcvNum++;
				matches.push_back(buf);

			}else if(rlen<sizeof(buf)){
				int less = 0;
				error++;
				while(true){
					less += rlen;
					if(less == 80){
						break;
					}
					recv(conn_fd,(MatchedLogRec *)&buf+less,sizeof(MatchedLogRec)-less,0);//read the remain datas
					try{
							if(rlen == 0){
								break;
							}else if(rlen<0){
								throw ServerException("Receiving data failed!\n");
							}
								
						}catch(ServerException e){	
							printf("%s\n",e.show())	;
						}				
				
			}
			rcvNum++;
			matches.push_back(buf);
	}
	}
}
